package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/RuiGuangServer/alarm"
	"github.com/RuiGuangServer/config"
	"github.com/RuiGuangServer/daemon"
	"github.com/RuiGuangServer/global"
	"github.com/RuiGuangServer/handlers"
	"github.com/RuiGuangServer/logs"
	"github.com/RuiGuangServer/tcpClient"
	"github.com/RuiGuangServer/tcpServer"
	"github.com/RuiGuangServer/testData"
	"github.com/RuiGuangServer/udpClient"
	"github.com/RuiGuangServer/utils"
)

var (
	daemonMode    = flag.Bool("d", false, "run as daemon")
	logger        *logs.AsyncLogger
	dataer        *logs.AsyncLogger
	wg            sync.WaitGroup // 用于等待所有客户端协程结束
	lastClearDate string         // 记录上次清空的日期，避免重复执行
)

func main() {
	flag.Parse()
	config.InitConfig("./config/config.ini")
	logger = utils.LogsStart()
	logger.Info("*********************开启服务*****************")
	dataer = utils.DataStart()
	defer shutdown()

	if *daemonMode {
		daemon.Daemonize(daemonMode)
		// 注意：守护进程成功后，原进程会退出，只有子进程会继续执行
	}

	// 创建可取消的上下文
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// 启动测试数据生成任务
	testData.StartTestDataGeneration(ctx)
	// 启动灯光检查协程
	startLightingChecker(ctx)
	// 客户端管理
	clients := startClients()

	// TCP服务器
	tcpServers := startTCPServer()

	// 启动航班计划清理任务
	startPlanCleaner(ctx)

	// 启动每日清空任务
	startDailyClearTask(ctx)

	// 监控
	go monitorSystemState()

	// 信号处理 - 修改为直接在主goroutine中处理
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// 等待信号或上下文取消
	select {
	case <-sigChan:
		logger.Info("Shutdown signal received")
	case <-ctx.Done():
	}

	// 清理
	stopServices(tcpServers, clients, cancel)
}

// startLightingChecker 启动灯光检查定时任务
func startLightingChecker(ctx context.Context) {
	// fmt.Printf("startLightingChecker****************\n")
	wg.Add(1)
	go func() {
		defer wg.Done()

		ticker := time.NewTicker(time.Duration(config.Config.CheckInter) * time.Millisecond)
		defer ticker.Stop()

		logger.Info("Starting lighting level checker")

		for {
			select {
			case <-ticker.C:
				alarm.CheckLightingLevels(logger)
			case <-ctx.Done():
				logger.Info("Stopping lighting level checker")
				return
			}
		}
	}()
}

func shutdown() {
	logger.Info("Shutting down services...")
	dataer.Close()
	logger.Close()
}

func startClients() []interface{ Stop() } {
	var clients []interface{ Stop() }
	var clientMutex sync.Mutex

	for _, cfg := range config.Config.Clients {
		if !cfg.State {
			continue
		}

		wg.Add(1)
		go func(cfg config.ClientConfig) {
			defer wg.Done()

			var client interface{ Stop() }
			switch cfg.Type {
			case 1:
				client = createTCPClient(cfg)
			case 2:
				client = createUDPClient(cfg)
			case 3:
				logger.Warn("HTTP client not implemented")
			default:
				logger.Error("Unknown client type: %d", cfg.Type)
			}

			if client != nil {
				clientMutex.Lock()
				clients = append(clients, client)
				clientMutex.Unlock()
			}
		}(cfg)
	}

	return clients
}

// 在 createTCPClient 函数中添加心跳超时设置
func createTCPClient(cfg config.ClientConfig) *tcpClient.TCPClient {
	logger.Info("Initializing TCP client for %s @ %s", cfg.Handler, cfg.Addr)
	// fmt.Printf("Initializing TCP\n")
	var handler tcpClient.HandlerFunc
	var heartbeatMsg []byte

	switch cfg.Handler {
	case "flightplan":
		// fmt.Printf("flightplan\n")
		handler = handlers.HandleFlightPlan
		heartbeatMsg = handlers.MsgFP("hb", nil)
	case "videorecog":
		// fmt.Printf("videorecog\n")
		handler = handlers.HandleVideoRecog
		heartbeatMsg = handlers.MsgVR(2)
		handlers.GetLightData()
	default:
		logger.Error("Unsupported TCP handler: %s", cfg.Handler)
		return nil
	}

	// fmt.Printf("tcp addr:%v\n", cfg.Addr)
	client := tcpClient.NewTCPClient(cfg.Addr, handler, cfg.Reconnect)
	client.SetHeartbeat(heartbeatMsg, time.Duration(config.Config.ClientHB)*time.Millisecond)

	// 设置心跳超时时间（建议为心跳间隔的3倍）
	heartbeatTimeout := time.Duration(config.Config.ClientHB) * time.Millisecond * 3
	client.SetHeartbeatTimeout(heartbeatTimeout)

	if err := client.Start(logger, dataer); err != nil {
		logger.Error("TCP client start failed: %v", err)
		if cfg.Reconnect {
			time.Sleep(time.Duration(config.Config.ClientSleep) * time.Millisecond)
			return createTCPClient(cfg) // 递归重连
		}
		return nil
	}

	// 启动后检查并请求灯光数据
	if cfg.Handler == "videorecog" {
		go func() {
			time.Sleep(2 * time.Second) // 等待连接建立
			handlers.CheckAndRequestLightData(client.SendMessage, logger)
		}()
	}

	return client
}

func createUDPClient(cfg config.ClientConfig) *udpClient.UDPClient {
	logger.Info("Initializing UDP client for %s @ %s", cfg.Handler, cfg.Addr)

	var handler udpClient.HandlerFunc
	switch cfg.Handler {
	case "adsb":
		handler = handlers.HandleADSB
	case "awos":
		handler = handlers.HandleAWOS
	case "weather":
		handler = handlers.HandleWeather
	default:
		logger.Error("Unsupported UDP handler: %s", cfg.Handler)
		return nil
	}

	client := udpClient.NewUDPClient(cfg.Addr, handler, cfg.Reconnect)
	if err := client.Start(logger, dataer); err != nil {
		logger.Error("UDP client start failed: %v", err)
		if cfg.Reconnect {
			time.Sleep(time.Duration(config.Config.ClientSleep) * time.Millisecond)
			return createUDPClient(cfg) // 递归重连
		}
		return nil
	}

	return client
}

func startTCPServer() *tcpServer.TCPServer {
	server := tcpServer.NewTCPServer(config.Config.TcpServer)
	wg.Add(1)
	go func() {
		defer wg.Done()
		logger.Info("TCP server starting on %s", config.Config.TcpServer)
		if err := server.Start(); err != nil {
			logger.Error("TCP server start error: %v", err)
		}
	}()
	return server
}

// 启动航班计划清理任务
func startPlanCleaner(ctx context.Context) {
	wg.Add(1)
	go func() {
		defer wg.Done()

		// 设置清理间隔（例如每分钟清理一次）
		cleanInterval := time.Duration(60000) * time.Millisecond
		ticker := time.NewTicker(cleanInterval)
		defer ticker.Stop()

		logger.Info("Starting flight plan cleaner with interval %v", cleanInterval)

		for {
			select {
			case <-ticker.C:
				cleanExpiredPlans() // 只清理过期，不清空
			case <-ctx.Done():
				logger.Info("Stopping flight plan cleaner")
				return
			}
		}
	}()
}

// 启动每日清空任务
func startDailyClearTask(ctx context.Context) {
	wg.Add(1)
	go func() {
		defer wg.Done()

		// 每分钟检查一次是否到了23:59
		ticker := time.NewTicker(1 * time.Minute)
		defer ticker.Stop()

		logger.Info("Starting daily plan clearer")

		for {
			select {
			case <-ticker.C:
				now := time.Now()
				currentTime := now.Format("15:04")
				today := now.Format("2006-01-02")

				// 在23:59执行清空（提前1分钟检查，更可靠）
				if currentTime == "23:59" && lastClearDate != today {
					logger.Info("Preparing to clear all flight plans at 23:59")

					// 计算到23:59:59的剩余时间
					nextMinute := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
					timeUntilClear := nextMinute.Sub(now)

					if timeUntilClear > 0 {
						// 等待到23:59:59再执行
						timer := time.NewTimer(timeUntilClear)

						select {
						case <-timer.C:
							clearAllPlans()
							lastClearDate = today
						case <-ctx.Done():
							timer.Stop()
							return
						}
					}
				}
			case <-ctx.Done():
				logger.Info("Stopping daily plan clearer")
				return
			}
		}
	}()
}

// 清理过期航班计划
func cleanExpiredPlans() {
	nowUnix := time.Now().Unix()
	logger.Debug("Cleaning expired flight plans at %d", nowUnix)

	var count int
	global.PlanMap.Range(func(key, value any) bool {
		plan := value.(*global.PlanState)
		if plan.Utime < plan.Stime && plan.Stime < nowUnix-7200 {
			global.PlanMap.Delete(key)
			landkey := fmt.Sprintf("landing_%v", key)
			takekey := fmt.Sprintf("takeoff_%v", key)
			alarm.RemoveMessageItem(landkey, logger)
			alarm.RemoveMessageItem(takekey, logger)
			logger.Debug("Deleted expired flight plan: %s (U_t:%d, S_t:%d)", key.(string), plan.Utime, plan.Stime)
		} else {
			count++
		}
		return true
	})

	logger.Info("Current flight plan count: %d", count)
}

// 清空所有航班计划
func clearAllPlans() {
	logger.Info("Clearing ALL flight plans at 23:59:59")

	var clearedCount int
	global.PlanMap.Range(func(key, value any) bool {
		global.PlanMap.Delete(key)
		landkey := fmt.Sprintf("landing_%v", key)
		takekey := fmt.Sprintf("takeoff_%v", key)
		alarm.RemoveMessageItem(landkey, logger)
		alarm.RemoveMessageItem(takekey, logger)
		clearedCount++
		return true
	})

	logger.Info("All flight plans cleared at 23:59:59, total cleared: %d", clearedCount)
}

func monitorSystemState() {
	ticker := time.NewTicker(time.Duration(config.Config.Monitor) * time.Millisecond)
	defer ticker.Stop()

	for range ticker.C {
		count := 0
		global.PlanMap.Range(func(_, _ any) bool {
			count++
			return true
		})

		if count > 0 {
			logger.Info("System status - Active tracks: %d", count)
		}
	}
}

func stopServices(server *tcpServer.TCPServer, clients []interface{ Stop() }, cancel context.CancelFunc) {
	logger.Info("Stopping TCP server...")
	server.Stop()

	logger.Info("Stopping all clients...")
	for _, client := range clients {
		client.Stop()
	}

	// 取消所有任务
	cancel()

	logger.Info("Waiting for all goroutines to finish...")
	wg.Wait()
	logger.Info("All services stopped")
}
